#include <iostream>
#include "httplib.h"
#include "ContactsException.h"
#include "add_contacts.pb.h"
using std::cin;
using std::cout;
using std::endl;
using std::cerr;
using namespace httplib;

const std::string serverip = "42.194.197.13";
const uint16_t serverport = 8080;

enum OPTIONS{
    QUIT = 0,
    ADD_,
    DEL,
    FIND_ALL,
    FIND_ONE,
};

void menu()
{
    // 只实现添加联系人的功能
    cout << "---------------------------------" << endl;
    cout << "---------- 1.添加联系人 ----------" << endl;
    cout << "---------- 2.删除联系人 ----------" << endl;
    cout << "---------- 3.查询所有联系人 -------" << endl;
    cout << "---------- 4.查询单个联系人 -------" << endl;
    cout << "------------   0.退出 ------------" << endl;
    cout << "---------------------------------" << endl;
}

void BuildAddContactsReq(add_contacts::AddContactsReq& req)
{
    cout << "请输入联系人姓名:";
    std::string name;
    std::getline(std::cin, name);
    req.set_name(name);

    std::cout << "请输入联系人年龄:";
    int age;
    std::cin >> age;
    std::cin.ignore(256, '\n');
    req.set_age(age);

    for (int i = 0; ; i++)
    {

        std::cout << "请输入联系人电话" << i + 1 << "(仅输入回车表示退出)" << ":";
        std::string number;
        std::getline(std::cin, number);
        if (number.empty()) break;
        add_contacts::AddContactsReq_Phone* phone = req.add_phones();
        phone->set_number(number);
        std::cout << "请输入联系人电话类型(1.移动电话 2.固定电话)" << ":";
        int op;
        std::cin >> op;
        std::cin.ignore(256, '\n');
        switch(op)
        {
            case 1:
                phone->set_type(add_contacts::AddContactsReq_Phone_PhoneType::AddContactsReq_Phone_PhoneType_MP);
                break;
            case 2:
                phone->set_type(add_contacts::AddContactsReq_Phone_PhoneType::AddContactsReq_Phone_PhoneType_TEL);
                break;
            default:
                break;
        }
    }
}

void AddContacts()
{
    Client cli(serverip, serverport);
    // 构造req
    add_contacts::AddContactsReq req;
    BuildAddContactsReq(req);

    // 序列化req
    std::string req_str;
    if (!req.SerializeToString(&req_str))
    {
        throw ContactsException("AddContactsReq序列化失败!");
    }

    std::string error_desc;
    // 发起post调用
    auto res = cli.Post("/contacts/add", req_str, "application/protobuf");
    if (!res)
    {
        error_desc.append("/contacts/add 连接异常!错误信息:")
            .append(httplib::to_string(res.error()));
        throw ContactsException(error_desc);
    }

    // 反序列化resp
    add_contacts::AddContactsResp resp;
    bool parse = resp.ParseFromString(res->body);
    if (res->status != 200 && !parse)
    {
        error_desc.append("/contacts/add 调用失败!")
        .append(std::to_string(res->status))
        .append("(").append(res->reason).append(")");
        throw ContactsException(error_desc);
    }
    else if (res->status != 200)
    {
        error_desc.append("/contacts/add 调用失败!")
        .append("(").append(res->reason).append(")")
        .append(resp.error_desc());
        throw ContactsException(error_desc);
    }
    else if (!resp.success())
    {
        error_desc.append("/contacts/add 结果异常!")
        .append("异常原因:")
        .append(resp.error_desc());
        throw ContactsException(error_desc);
    }

    // 结果打印
    cout << "新增联系人成功，联系人ID:" << resp.uid() << endl;
}

int main()
{
    while (true)
    {
        menu();
        int op = 0;
        cout << "--->" << "请选择:";
        cin >> op;
        cin.ignore(256, '\n');
        try{
            switch(op)
            {
                case QUIT:
                    cout << "--->退出！" << endl;
                    return 0;
                case OPTIONS::ADD_:
                    AddContacts();
                    break;
                case OPTIONS::DEL:
                case OPTIONS::FIND_ALL:
                case OPTIONS::FIND_ONE:
                    break;
                default:
                    cout << "--->选择有误！请重新选择" << endl;
                    break;
            }
        }catch(const ContactsException& e)
        {
            std::cout << "--->操作通讯录时发生异常" << std::endl;
            std::cout << "--->异常信息: " << e.what() << std::endl;
            return 1;
        }
    }

    return 0;
}

// int main()
// {
//     Client cli(serverip, serverport);
//     Result resp1 = cli.Post("/test-post");
//     if (resp1->status == 200)
//     {
//         cout << "调用post成功!" <<endl;
//     }
//     Result resp2 = cli.Get("/test-get");
//     if (resp2->status == 200)
//     {
//         cout << "调用get成功!" << endl;
//     }

//     return 0;
// }